实现 new 操作符
new 操作符可以把一个构造函数实例化成一个对象。
new 操作符到底做了什么
- 创建一个空对象(即
{}
)且构造函数的 this 对象引用该对象,同时继承了该函数的原型。 - 方法和属性被加入到 this 引用的对象中。
- 如果该函数没有返回对象,则返回 this。
实现
function newFn(fn, ...args) {
// 不是一个函数,抛出异常
if (typeof fn !== 'function') throw new Error(`${fn} not a function`)
// 1. 创建一个空对象 obj
const obj = {}
// 2. 继承该函数的原型
Object.setPrototypeOf(obj, fn.prototype)
// 3. 将构造函数的 this 的上下文指向 obj,同时传入剩下的参数,并执行
const result = fn.apply(obj, args)
// 4. 如果构造函数返回的是一个对象则将这个返回值正常返回,否则返回第一步创建的 obj
return result instanceof Object ? result : obj
}
通过构造函数实例化出来的对象,可以访问到构造函数的原型对象,所以使用 Object.setPrototype
将两者联系起来。Object.setPrototypeOf(obj, fn.prototype)
等同于 obj.__proto__ = fn.prototype
。之所以不这么做,是因为通常认为 Object.setPrototype
比直接使用 Object.prototype.__proto__
更安全。